//
//  BBLightboxView.m
//  BBTUIOTest
//
//  Created by ben smith on 22/09/08.
//  Copyright 2008 __MyCompanyName__. All rights reserved.
//

#import "BBLightboxView.h"
#import "BBTUIOCursor.h"
#import "BBPhotoLayer.h"
#import "BBGestureDecoder.h"


@implementation BBLightboxView

-(void)setup
{
	[self setWantsLayer:YES];
	
	gestureDecoder = [[BBGestureDecoder alloc] init];
	
	photoContainer = [[CALayer layer] retain];
	photoContainer.anchorPoint = CGPointMake(0.5, 0.5);
	photoContainer.position = CGPointZero;
	//	mainLayer.name = @"mainLayer";
//	mainLayer.delegate = self;
//	[self setLayer:mainLayer];
//	self.layer.delegate = self;
//	[self.layer setNeedsDisplay];
	
	[self loadPhotos];
	[self resetLayers];
}


-(void)loadPhotos
{
	if ([[NSUserDefaults standardUserDefaults] objectForKey:@"BBPhotoDirectory"] == nil) return;
	NSString* dirname = [[NSUserDefaults standardUserDefaults] objectForKey:@"BBPhotoDirectory"];
	for (NSString* filename in [[NSFileManager defaultManager] directoryContentsAtPath:dirname]) {
		NSImage *photo = [[NSImage alloc] initWithContentsOfFile:[dirname stringByAppendingPathComponent:filename]];
		
		
		BBPhotoLayer * photoLayer = [BBPhotoLayer layer];
		[photoLayer setImageContents:photo];
		photoLayer.name = filename;
		CATransform3D xform = CATransform3DMakeScale(0.5, 0.5, 1.0f);
		photoLayer.transform = xform;
		float zDistance = 420.;
		photoLayer.sublayerTransform = xform;
		photoLayer.anchorPoint = CGPointMake(0.5,0.5);
		photoLayer.position = CGPointZero;
//		photoLayer.position = CGPointMake(NSMidX([self bounds]),NSMidY([self bounds]));
		CALayer * carrierLayer = [CALayer layer];
		CATransform3D sublayerTransform = CATransform3DIdentity; 
		sublayerTransform.m34 = 1. / -zDistance;
		carrierLayer.sublayerTransform = sublayerTransform;
		[carrierLayer addSublayer:photoLayer];
		[photoContainer addSublayer:carrierLayer];
	  [photo release];
	}
	[self.layer addSublayer:photoContainer];
}

-(void)resetLayers
{
	offset = CGPointMake(0, 0);
	[photoContainer removeFromSuperlayer];
	[self.layer addSublayer:photoContainer];
	for (CALayer* layer in [photoContainer sublayers]) {
		layer.position = CGPointMake(NSMidX([self bounds]),NSMidY([self bounds]));		
	}
}

-(void)blobCycleDone
{
	// do the thing
	// find all the htis of the layers and pass on the fun
	for (BBTUIOCursor * cursor in cursors) {
		[self dispatchCursor:cursor];
	}
	
	[CATransaction begin];
	// make sure the dragging happens immediately. we set a specific
	// value here in case we want to it be nearly instant (0.1) later        
	[CATransaction setValue: [NSNumber numberWithBool:0.0]
									 forKey: kCATransactionAnimationDuration];
	
	[[photoContainer sublayers] makeObjectsPerformSelector:@selector(finishCursorCycle)];

	// now handle my own events
	[gestureDecoder finishCursorCycle];
	[self.layer removeAllAnimations];	

	if (gestureDecoder.eventMask & BBDragEventMask) [self handleDrag];
	if (gestureDecoder.eventMask & BBRotateEventMask) [self handleRotate];
//	if (gestureDecoder.eventMask & BBScaleEventMask) [self handleScale];
	
	[CATransaction commit];

	[self setNeedsDisplay:YES];
}

-(void)dispatchCursor:(BBTUIOCursor*)aCursor
{
	// need to scale the 0..1 style TUIO coordinates to our bounds
	// TODO: cache these
	float scaleX = NSWidth([self bounds]);
	float scaleY = NSHeight([self bounds]);
	
	NSPoint loc = [aCursor position];
	
	// flip the y, it is from the top down in TUIO parlance,
	// but our views are bottom up
	loc.y = 1.0 - loc.y;
	
	loc.x *= scaleX;
	loc.y *= scaleY;

	aCursor.screenPosition = loc;
	
	CALayer* hitLayer = [photoContainer hitTest:CGPointMake(loc.x, loc.y)];
	if (hitLayer == nil) {
		[gestureDecoder addCursor:aCursor];
		return;		
	}
	[[(BBPhotoLayer*)hitLayer gestureDecoder] addCursor:aCursor];
}

-(void)mouseDown:(NSEvent*)theEvent
{
	NSPoint loc = [[[self window] contentView] convertPoint:[theEvent locationInWindow] toView:self];

	// fake a cursor event	
	CALayer* hitLayer = [photoContainer hitTest:CGPointMake(loc.x, loc.y)];
	if (hitLayer == nil) {
		[gestureDecoder setCentroid:NSPointToCGPoint(loc)];
		[gestureDecoder addMouseDownEvent:theEvent];
		return;		
	}
	[[(BBPhotoLayer*)hitLayer gestureDecoder] setCentroid:NSPointToCGPoint(loc)];
	[[(BBPhotoLayer*)hitLayer gestureDecoder] addMouseDownEvent:theEvent];
	[self blobCycleDone];
}

-(void)mouseDragged:(NSEvent*)theEvent
{
	NSPoint loc = [[[self window] contentView] convertPoint:[theEvent locationInWindow] toView:self];
	
	// fake a cursor event	
	CALayer* hitLayer = [photoContainer hitTest:CGPointMake(loc.x, loc.y)];
	if (hitLayer == nil) {
		[gestureDecoder setCentroid:NSPointToCGPoint(loc)];
		[gestureDecoder addMouseDraggedEvent:theEvent];
		[self blobCycleDone];
		return;		
	}
	[[(BBPhotoLayer*)hitLayer gestureDecoder] setCentroid:NSPointToCGPoint(loc)];

	[[(BBPhotoLayer*)hitLayer gestureDecoder] addMouseDraggedEvent:theEvent];
	[self blobCycleDone];
}

-(void)mouseUp:(NSEvent*)theEvent
{
	[gestureDecoder addMouseUpEvent:theEvent];
	
	for (CALayer* layer in [photoContainer sublayers]) {
		[[(BBPhotoLayer*)layer gestureDecoder] addMouseUpEvent:theEvent];
	}
//	[self blobCycleDone];
}

-(void)finishCursorCycle
{
	[gestureDecoder finishCursorCycle];
	// figure out what the hell happened
}

-(void)handleDrag
{
	// now I have 2 matching cursors, it is a drag
	CGPoint dragVector = gestureDecoder.vector;
//	offset = CGPointMake(offset.x + dragVector.x, offset.y + dragVector.y);
	CATransform3D translate = CATransform3DMakeTranslation(dragVector.x, dragVector.y, 0);	
	photoContainer.sublayerTransform = CATransform3DConcat(photoContainer.sublayerTransform, translate);
}


-(void)handleRotate
{
	//	angle += gestureDecoder.angle;
	//	CATransform3D totalTransform = self.transform;
	CATransform3D rotate = CATransform3DMakeRotation (gestureDecoder.angle, 0.0, 0.0, 1.0);
	photoContainer.sublayerTransform = CATransform3DConcat(photoContainer.sublayerTransform, rotate);
}


-(void)handleScale
{
	//	angle += gestureDecoder.angle;
	//	CATransform3D totalTransform = self.transform;
	CATransform3D scale = CATransform3DMakeScale(gestureDecoder.scale, gestureDecoder.scale, 1.0) ;
	self.layer.transform = CATransform3DConcat(self.layer.transform, scale);
}



// the magic happens here
- (void)drawRect:(NSRect)rect 
{
	// draw the pretty gradient
	[self.backgroundGradient drawInRect:self.bounds angle:90.0];
	
	// draw the blobs
//	[self drawBlobs];
	
	//draw our label
	[self drawText:@"TUIO Test View" centeredAtPoint:NSMakePoint(NSMidX([self bounds]), 10)];
}




- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
	NSGraphicsContext *nsGraphicsContext;
	
	nsGraphicsContext = [NSGraphicsContext graphicsContextWithGraphicsPort:ctx
																																 flipped:NO];
	[NSGraphicsContext saveGraphicsState];
	
	[NSGraphicsContext setCurrentContext:nsGraphicsContext];
	if (layer == self.layer) [self drawRect:[self bounds]];
	if (layer != self.layer) [self drawBlobs];
	// ...Draw content using NS APIs..
	[NSGraphicsContext restoreGraphicsState];
}




@end
